package org.hawk.gwt.ppc.parser.impl;

import org.hawk.gwt.ppc.parser.Descriptor;
import org.hawk.gwt.ppc.parser.Token;
import org.hawk.gwt.ppc.utils.PreprocessorException;

/**
 * Type of descriptors that may be expected in different parts of Java compilation unit.
 * 
 * @author alex.bereznevatiy@gmail.com
 */
enum DescriptorType {
	
	/**
	 * Whole compilation unit.
	 */
	COMPILATION_UNIT (new CompilationUnitDescriptorParser()),
	
	/**
	 * Package declaration
	 */
	PACKAGE (new PackageDescriptorParser()),
	
	/**
	 * Imports section
	 */
	IMPORTS (new ImportsDescriptorParser()),
	
	/**
	 * Represents class or interface or enum or annotation
	 */
	CLASS (new ClassDescriptorParser()),
	
	/**
	 * Any block of code (possibly with modifiers).
	 * E.g. synchronized block or static initializer or
	 * just initialization block or method body.
	 * Anything that is enclosed between { and } brackets.
	 */
	BLOCK (new BlockDescriptorParser()),
	
	/**
	 * Parses annotations
	 */
	ANNOTATION (new AnnotationDescriptorParser()),
	
	/**
	 * Expression that takes single "line".
	 * Strictly this is not always whole line but from the end of previous expression
	 * till ';' symbol. 
	 */
	LINE_EXPRESSION (new LineExpressionDescriptorParser()),
	
	/**
	 * Line expression that begins with java keyword and has special meaning (e.g. return expression).
	 */
	KEYWORD_EXPRESSION (new KeywordExpressionDescriptorParser()),
	
	/**
	 * Any block-like expression (excluding block). E.g. if, while, try etc.
	 */
	BLOCK_EXPRESSION (new BlockExpressionDescriptorParser()),
	
	/**
	 * Single variable declaration (perhaps with annotation).
	 */
	VARIABLE(new VariableDescriptorParser()),
	
	/**
	 * Special type describing end of file
	 */
	EOF (null);
	
	private DescriptorParser parser;
	
	private DescriptorType(DescriptorParser parser) {
		this.parser = parser;
	}
	
	/**
	 * @param token
	 * @return <code>true</code> if token is acceptable as the beginning of this type.
	 */
	public boolean accepts(Token token) {
		return parser.accepts(token);
	}
	
	/**
	 * Invokes parsing using specific descriptor parser.
	 * @param rootParser
	 * @param tokenizer to read tokens
	 * @param params - additional parameters for parsing if any
	 * @return descriptor matching this descriptor type.
	 * @throws PreprocessorException
	 */
	public Descriptor parse(TokenBasedJavaParser rootParser, TokenSource tokenizer, Object...params) 
			throws PreprocessorException {
		return parser.parse(rootParser, tokenizer, params);
	}
}
